package framework.catalog;

import junit.framework.Assert;

import org.openqa.selenium.By;
import framework.elements.Button;
import framework.elements.Label;
import framework.elements.Link;

/** Обрабатывает форму каталога с деревом.
 */
public class CatalogWithTreeForm extends BaseCatalog{

	/** Базовый конструктор.
	 */
	public CatalogWithTreeForm() {
		super(By.id("goodssearch"), "Справочник");
	}

	private final String tree = "//div[@id='tree']";
	private final String treeContent = "/ul/li/span[contains(@class,'dynatree-has-children')]";
	private final String openBranch = "/span[@class='dynatree-expander'][contains(.,'')]";
	private final String itemTitle = "/span[@class='dynatree-title']";
	private final String closedBranch = "[contains(@class,'dynatree-ico-cf')]";
	private final String checkbox = "//span[@class='dynatree-checkbox']";
	private final String selectedItem = "/span[contains(@class,'dynatree-selected')]";
	private Button find = new Button(By.xpath("//input[@value='Найти']"), "Найти");
	private Button choise = new Button(By.xpath("//input[@value='Выбрать']"), "Выбрать");
	private Button reset = new Button(By.xpath("//input[@value='Сбросить']"), "Сбросить");
	private final String foundItemTemplate = "//span[contains(.,'%s')]";
	private Label message = new Label(By.xpath("//div[contains(@class, 'msgbox-confirm')]/form"), "Предупреждающее сообщение");
	private Button cont= new Button(By.xpath("//button[contains(.,'Продолжить')]"), "Продолжить");
	private Label expOpenedTree = new Label(By.xpath(tree +  "/ul[1]/li[1]/span[contains(@class,'dynatree-ico-ef')]"), "Развернутое дерево поиска");
	private Label expClosedTree = new Label(By.xpath(tree +  "/ul[1]/li[1]/span[contains(@class,'dynatree-ico-cf')]"), "Свернутое дерево поиска");
	private final String selectingItem = "//li[@class='dynatree-lastsib']//span[contains(@class,'dynatree-exp-cl')]";
	private Link randomItem = new Link(By.xpath("//ul[@class='dynatree-container']//li"), "Первый элемент из списка");
	private Link randomItemCode = new Link(By.xpath("//ul[@class='dynatree-container']//li//span[@class='code']"), "Код первого элемента из списка");
	private Link randomItemLink = new Link(By.xpath("//ul[@class='dynatree-container']//li//a[@class='dynatree-title']"), "Выбираемый элемент");

	/**
	 * Открывает первую попавшуюся ветку дерева поиска до ее основания, выбирает первый чекбокс
	 * @return корневое значение ветки
	 */
	public final String openRootOfBranch(){
		Label l = new Label(By.xpath(tree + treeContent + itemTitle), "Ветка");
		Link open = new Link(By.xpath(tree + treeContent + openBranch), "Открыть ветку");
		Label openedBranch = new Label(By.xpath(tree + treeContent + "[contains(@class, 'dynatree-ico-ef')]"), "Открытая ветка");
		Boolean isRoot = true;
		String branchName = "";
		while(isRoot){
			if(l.isPresent()){
				branchName = l.getText();
				open.click();
				if(!openedBranch.isPresent()){
					open.clickWithoutLog();
				}
				Assert.assertEquals("Ветка " + branchName + " не открылась", true, openedBranch.isPresent());
				logger.info("Открываем ветку: " + branchName);
				l = new Label(By.xpath(l.getLocator().toString().replace("/span[@class='dynatree-title']", "").replace("By.xpath: ", "").replace("/span[contains(@class,'dynatree-has-children')]", "").replace(closedBranch, "") + treeContent + closedBranch), "Ветка");
				open = new Link(By.xpath(open.getLocator().toString().replace("/span[contains(@class,'dynatree-has-children')]", "").replace(openBranch, "").replace("By.xpath: ", "") + treeContent + openBranch), "Открыть ветку");
				openedBranch = new Label(By.xpath(openedBranch.getLocator().toString().replace("By.xpath: ", "").replace("/span[contains(@class,'dynatree-has-children')]", "").replace("[contains(@class, 'dynatree-ico-ef')]","") +  treeContent + "[contains(@class, 'dynatree-ico-ef')]"), "Открытая ветка");
			}else{
				break;
			}
		}
		l = new Label(By.xpath(l.getLocator().toString().replace("/span[@class='dynatree-title']", "").replace("By.xpath: ", "").replace("/span[contains(@class,'dynatree-has-children')]", "").replace(closedBranch, "") + "/" + itemTitle),"");
		String text = l.getText();
		Label checkValue = new Label(By.xpath(l.getLocator().toString().replace("By.xpath: ", "").replace("/" + itemTitle, "") + checkbox), "Чекбокс " + name + ": " + text);
		checkValue.clickAndWait();
		Label selectedValue = new Label(By.xpath(l.getLocator().toString().replace("By.xpath: ", "").replace("/" + itemTitle, "") + selectedItem), "Чекбокс: " + text);
		Assert.assertEquals("Чекбокс: " + text + " является невыбранным.", true, selectedValue.isPresent());
		logger.info("Чекбокс: " + text + " является выбранным.");
		return text;
	}

	/** Вводит искомый текст
	 * @param text текст
	 */
	private void typeSearchText(final String text){
		searchTxb().setText(text);
	}

	/** Нажимает кнопку найти и ждет появляющееся предупреждающее сообщение
	 * 	После обрабатывает его
	 * @param waitWarningMessage true если нужно ждать предупреждающее сообщение
	 */
	private void clickFindBtn(final Boolean waitWarningMessage){
		for(int i = 0; i<2; i++){
			find.click();
			if(waitWarningMessage){
				message.waitAndAssertIsPresent();
				logger.info("Предупреждающее сообщение: " + message.getText());
				Assert.assertEquals("Сообщение содержит некорректный текст: " + "В классификаторе уже выбрана позиция. Выполнение операции приведет к сбросу выбранного значения. Вы уверены, что хотите продолжить?", true, message.getText().contains("В классификаторе уже выбрана позиция. Выполнение операции приведет к сбросу выбранного значения. Вы уверены, что хотите продолжить?"));
				cont.click();
			}
			if(expOpenedTree.isPresent()) {
				break;
			}
		}
		expOpenedTree.waitAndAssertIsPresent();
	}

	/** Ищет по коду, наименованию или их части
	 * @param partText часть для поиска
	 * @param fullText ожидаемый результат поиска
	 * @param waitWarningMessage если перед этим уже было выбрано значение, то будет показано предупреждающее сообщение
	 * 							true - если это так
	 */
	public final void searchItem(final String partText, final String fullText, final Boolean waitWarningMessage){
		typeSearchText(partText);
		clickFindBtn(waitWarningMessage);
		Label l  = new Label(By.xpath(String.format(foundItemTemplate, fullText)),"Искомое значение: " + fullText);
		l.waitAndAssertIsPresent();
		logger.info("Желаемая информация найдена: " + fullText);
	}

	/**
	 * Нажимает на кнопку Сбросить и ждет пока дерево не закроется, а строка поиска очистится
	 */
	public final void resetSearch(){
		for(int i = 0; i <2; i++){
			reset.clickAndWait();
			if(expClosedTree.isPresent()) {
				break;
			}
		}
		expClosedTree.waitAndAssertIsPresent();
		Assert.assertEquals("Значение поля поиска содержит некорректное сообщение: Введите наименование или код.", true, searchTxb().getAttribute("value").contains("Введите наименование или код"));
		logger.info("Значение поля поиска содержит корректное значение: " + searchTxb().getAttribute("value"));
		Label l = new Label(By.xpath(tree + treeContent + "[contains(@class, 'dynatree-ico-ef')]"), "Открытая ветка");
		Assert.assertEquals("После очистки некая ветка осталась открытой.",false, l.isPresent());
		logger.info("Все ветки после очистки поля поиска закрыты");
	}

	/**
	 * Находит через поиск значение, выбирает его и ждет закрытия окна справочника.
	 * @param text код или наименование искомого значения
	 * @return название выбранного элемента
	 */
	public final String searchAndSelect(final String text){
		searchItem(text, text, false);
		Label value  = new Label(By.xpath(selectingItem + "/span[@class='dynatree-title']"),"Выбираемое значение");
		String name = value.getText();
		Label chb  = new Label(By.xpath(selectingItem + "//span[@class='dynatree-checkbox']"),"Чекбокс: " + name);
		chb.clickAndWait();
		Label selChb  = new Label(By.xpath(selectingItem + "[contains(@class,'dynatree-selected')]" + "//span[@class='dynatree-title'][contains(.,'" + name + "')]"),"Чекбокс: " + name);
		selChb.waitAndAssertIsPresent();
		choise.clickAndWaitForCloseWindow();
		return name;
	}

	/**
	 * Выбирает из справочника с деревом первый элемент.
	 * Необходимо учитывать, что дерево не содержит чекбоксов.
	 * После этого ждет закрытия окна справочника.
	 * @return название выбранного элемента
	 */
	public final String selectRandomItemWithoutOpeningTree(){
		randomItem.waitAndAssertIsPresent();
		String text = randomItem.getText();
		logger.info("Выбираемый элемент содержит текст: " + text);
		randomItemLink.clickAndWaitForCloseWindow();
		return text;
	}

	/**
	 * Возвращает код выбираемого элемента
	 * @return код выбранного элемента
	 */
	public final String getRandomItemCode(){
		randomItemCode.waitAndAssertIsPresent();
		String text = randomItemCode.getText();
		logger.info("Выбираемый элемент содержит код: " + text);
		return text;
	}

	/** Нажимает кнопку выбрать
	 */
	public void clickChoiseBtn(){
		choise.jsClickAndWaitForCloseWindow();
	}
}
